<template>
  <div ref="sheetContainer" v-bind:id="sheetContainerId" class="grid"></div>
</template>

<script>
import Spreadsheet from "x-data-spreadsheet";
import zhCN from "x-data-spreadsheet/src/locale/zh-cn";
import _ from "lodash";
import * as Excel from "exceljs/dist/exceljs";
import * as tinycolor from "tinycolor2";
import { postUploadFilePrivate } from "@/api/management/user";
export default {
  name: "xspreadsheet",
  props: {
    //列数
    ColumnCount: {
      type: Number,
      default: () => 999,
    },
    //列宽度
    ColumnWidth: {
      type: Number,
      default: () => 100,
    },
    //行数
    RowCount: {
      type: Number,
      default: () => 999,
    },
    //表名
    SheetName: {
      type: String,
      default: () => [],
    },
    //表头
    Headers: {
      type: Array,
      default: () => [],
    },
    Records: {
      type: Array,
      default: () => [],
    },
    File: {
      type: null,
      default: () => null,
    },
    ExportJsonProperties: {
      type: Array,
      default: () => [],
    },
    onlyRead: {
      type: Boolean,
      default: () => false,
    },
    DataSource: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      maxColsProps: 99,
      maxRowsProps: 99,
      xs: null,
      sheet: null,
      sheetContainerId: this.generateGuid(),
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.loadData();
      // this.init();
      // this.scrollInit();
    });
  },
  // computed: {
  //   maxCols() {
  //     return this.maxColsProps
  //   },
  //   maxRows() {
  //     return this.maxRowsProps
  //   }
  // },
  watch: {
    onlyRead: {
      handler(newV, oldV) {
        this.$nextTick(() => {
          this.setOnlyRead(newV);
        });
      },
    },
    File: {
      handler(newV, oldV) {
        this.$nextTick(() => {
          this.loadExcelFile(newV);
        });
      },
    },
    Headers: {
      deep: true,
      handler(newV) {
        console.log("Headers", newV);
        let result = [];
        if (Array.isArray(newV) && newV.length > 0) {
          let headerRow = { cells: [] };
          for (let i = 0; i < newV.length; i++) {
            headerRow.cells.push({
              text: newV[i],
              editable: false,
              style: 0,
            });
          }
          result.push(headerRow);
        }
        if (Array.isArray(this.Records) && this.Records.length > 0) {
          for (let i = 0; i < this.Records.length; i++) {
            let recordRow = { cells: [] };
            if (JSON.stringify(this.Records[i]) != "{}") {
              for (let k = 0; k < this.ExportJsonProperties.length; k++) {
                recordRow.cells.push({
                  text: this.Records[i][this.ExportJsonProperties[k]] + "",
                  editable: true,
                  style: 1,
                });
              }
            } else {
              for (let i = 0; i < this.ColumnCount; i++) {
                recordRow.cells.push({
                  text: "",
                  editable: true,
                  style: 1,
                });
              }
            }
            result.push(recordRow);
          }
        }
        this.DataSource = result;
      },
    },
    Records: {
      deep: true,
      handler(newV) {
        console.log("Records", newW);
        let result = [];
        if (Array.isArray(this.Headers) && this.Headers.length > 0) {
          let headerRow = { cells: [] };
          for (let i = 0; i < this.Headers.length; i++) {
            headerRow.cells.push({
              text: this.Headers[i],
              editable: false,
              style: 0,
            });
          }
          result.push(headerRow);
        }
        if (Array.isArray(newV) && newV.length > 0) {
          for (let i = 0; i < newV.length; i++) {
            let recordRow = { cells: [] };
            if (JSON.stringify(newV[i]) != "{}") {
              for (let k = 0; k < this.ExportJsonProperties.length; k++) {
                recordRow.cells.push({
                  text: newV[i][this.ExportJsonProperties[k]] + "",
                  editable: true,
                  style: 1,
                });
              }
            } else {
              for (let i = 0; i < this.ColumnCount; i++) {
                recordRow.cells.push({
                  text: "",
                  editable: true,
                  style: 1,
                });
              }
            }
            result.push(recordRow);
          }
        }
        this.DataSource = result;
      },
    },
    DataSource: {
      handler(newW) {
        console.log("watchDataSource", newW);
        if (this.xs) {
          this.xs.loadData([
            {
              name: this.SheetName,
              styles: [],
              rows: newW,
            },
          ]);
        }
      },
      deep: true,
    },
  },
  methods: {
    setOnlyRead(newV) {
      if (this.xs) {
        this.xs.options.mode = newV ? "read" : "edit";
        // this.xs.reRender();
      }
    },
    generateGuid() {
      const randomChars = "abcdefghijklmnopqrstuvwxyz0123456789";
      let guid = "";
      for (let i = 0; i < 32; i++) {
        guid += randomChars.charAt(
          Math.floor(Math.random() * randomChars.length)
        );
      }
      return guid;
    },
    // 初始化表格
    async init() {
      if (this.xs) {
        // window.xs.destroy();
        // 1. 移除事件监听器
        this.xs = null;
        // 2. 清空容器元素
        const container = document.getElementById(this.sheetContainerId);
        if (container) {
          while (container.firstChild) {
            container.removeChild(container.firstChild);
          }
        }
        console.log("销毁表格");
      }
      if (
        this.$refs.sheetContainer &&
        this.$refs.sheetContainer.offsetHeight &&
        this.$refs.sheetContainer.offsetWidth
      ) {
        //设置中文
        Spreadsheet.locale("zh-cn", zhCN);
        window.xs = this.xs = await new Spreadsheet(
          document.getElementById(this.sheetContainerId),
          {
            mode: this.onlyRead ? "read" : "edit", //edit||read
            showToolbar: false,
            showGrid: true,
            showContextmenu: false,
            showBottomBar: false,
            view: {
              height: () =>
                this.$refs.sheetContainer &&
                this.$refs.sheetContainer.offsetHeight &&
                _.isNumber(this.$refs.sheetContainer.offsetHeight)
                  ? this.$refs.sheetContainer.offsetHeight
                  : 0,
              width: () =>
                this.$refs.sheetContainer &&
                this.$refs.sheetContainer.offsetWidth &&
                _.isNumber(this.$refs.sheetContainer.offsetWidth)
                  ? this.$refs.sheetContainer.offsetWidth
                  : 0,
            },
            formats: [],
            fonts: [],
            formula: [],
            row: {
              len: 999 || this.RowCount,
              height: 25,
            },
            col: {
              len: 999 || this.ColumnCount,
              width: this.ColumnWidth,
              indexWidth: 60,
              minWidth: 60,
            },
          }
        );
        console.log("init结束");

        // //抛出事件
        this.xs.on("cell-selected", (cell, ri, ci) => {
          this.$emit("cell-selected", cell, ri, ci);
          // console.log(
          //   " xs.data.getSelectedCellStyle();",
          //   xs.data.getSelectedCellStyle()
          // );
        });
        this.xs.on("cells-selected", (cell, { sri, sci, eri, eci }) => {
          this.$emit("cells-selected", cell, { sri, sci, eri, eci });
        });
        this.xs.on("cell-edited", (text, ri, ci) => {
          let cell = this.xs.sheet.data.getCell(ri, ci);
          if (cell.text && cell.text.includes("=")) {
            cell.formula = cell.text;
          }
          this.$emit("cell-edited", cell, ri, ci);
        });
        this.xs.on("change", (data) => {
          this.$emit("change", this.xs.getData());
          // this.$emit("change", data);
        });
        // this.loadData();
      }
    },
    //获取sheet行数列数
    async calculateMaxRowsAndColumnsPerSheet(data) {
      const result = {};
      if (!data) {
        return;
      }
      // 遍历每个工作表
      data.forEach((sheet, index) => {
        let maxRows = 0;
        let maxColumns = 0;

        // 遍历每个行
        Object.keys(sheet.rows).forEach((rowIndex) => {
          const rowNumber = parseInt(rowIndex, 10);
          if (!isNaN(rowNumber)) {
            // 检查 rowIndex 是否是一个有效的数字
            maxRows = Math.max(maxRows, rowNumber + 1); // 行索引从 0 开始，因此需要加 1
          }

          // 遍历每个单元格
          const row = sheet.rows[rowIndex];
          if (row.cells) {
            // 检查 row.cells 是否存在
            Object.keys(row.cells).forEach((colIndex) => {
              const colNumber = parseInt(colIndex, 10);
              if (!isNaN(colNumber)) {
                // 检查 colIndex 是否是一个有效的数字
                maxColumns = Math.max(maxColumns, colNumber + 1); // 列索引从 0 开始，因此需要加 1
              }
            });
          }
        });
        result[index] = { maxRows, maxColumns };
      });
      return result;
    },
    async loadData(workbookData) {
      if (!workbookData) {
        return;
      }
      await this.init();
      if (this.xs) {
        let length = await this.calculateMaxRowsAndColumnsPerSheet(
          workbookData
        );

        let loadData = [];
        if (workbookData) {
          loadData = workbookData;
        }
        setTimeout(async () => {
          await this.xs.loadData(loadData);
          const data = this.xs.getData();
          data[0].rows.len = length[0].maxRows || 999;
          data[0].cols.len = length[0].maxColumns || 999;
          // console.log("data", data);
          await this.xs.loadData(data);
          this.$emit("loaded", workbookData);
          //刚打开表格时初始化数据，因为会默认选中A1
          this.$emit("initA1", this.xs.sheet.data.getCell(0, 0));
        });
      }
    },
    // 导入excel
    loadExcelFile(file) {
      if (file) {
        const wb = new Excel.Workbook();
        const reader = new FileReader();
        reader.readAsArrayBuffer(file);
        reader.onload = () => {
          const buffer = reader.result;
          // 微软的 Excel ColorIndex 一个索引数字对应一个颜色
          const indexedColors = [
            "000000",
            "FFFFFF",
            "FF0000",
            "00FF00",
            "0000FF",
            "FFFF00",
            "FF00FF",
            "00FFFF",
            "000000",
            "FFFFFF",
            "FF0000",
            "00FF00",
            "0000FF",
            "FFFF00",
            "FF00FF",
            "00FFFF",
            "800000",
            "008000",
            "000080",
            "808000",
            "800080",
            "008080",
            "C0C0C0",
            "808080",
            "9999FF",
            "993366",
            "FFFFCC",
            "CCFFFF",
            "660066",
            "FF8080",
            "0066CC",
            "CCCCFF",
            "000080",
            "FF00FF",
            "FFFF00",
            "00FFFF",
            "800080",
            "800000",
            "008080",
            "0000FF",
            "00CCFF",
            "CCFFFF",
            "CCFFCC",
            "FFFF99",
            "99CCFF",
            "FF99CC",
            "CC99FF",
            "FFCC99",
            "3366FF",
            "33CCCC",
            "99CC00",
            "FFCC00",
            "FF9900",
            "FF6600",
            "666699",
            "969696",
            "003366",
            "339966",
            "003300",
            "333300",
            "993300",
            "993366",
            "333399",
            "333333",
          ];
          wb.xlsx.load(buffer).then((workbook) => {
            let workbookData = [];
            workbook.eachSheet((sheet, sheetIndex) => {
              // 构造x-data-spreadsheet 的 sheet 数据源结构
              let sheetData = {
                name: sheet.name,
                styles: [],
                rows: {},
                merges: [],
              };
              // 收集合并单元格信息
              let mergeAddressData = [];
              console.log("sheet._merges", sheet._merges);

              for (let mergeRange in sheet._merges) {
                sheetData.merges.push(sheet._merges[mergeRange].shortRange);
                let mergeAddress = {};
                // 合并单元格起始地址
                mergeAddress.startAddress = sheet._merges[mergeRange].tl;
                // 合并单元格终止地址
                mergeAddress.endAddress = sheet._merges[mergeRange].br;
                // Y轴方向跨度
                mergeAddress.YRange =
                  sheet._merges[mergeRange].model.bottom -
                  sheet._merges[mergeRange].model.top;
                // X轴方向跨度
                mergeAddress.XRange =
                  sheet._merges[mergeRange].model.right -
                  sheet._merges[mergeRange].model.left;
                mergeAddressData.push(mergeAddress);
              }
              sheetData.cols = {};
              for (let i = 0; i < sheet.columns && sheet.columns.length; i++) {
                sheetData.cols[i.toString()] = {};
                if (sheet.columns[i].width) {
                  // 不知道为什么从 exceljs 读取的宽度显示到 x-data-spreadsheet 特别小, 这里乘以8
                  sheetData.cols[i.toString()].width =
                    sheet.columns[i].width * 8;
                } else {
                  // 默认列宽
                  sheetData.cols[i.toString()].width = 100;
                }
              }

              // 遍历行
              sheet.eachRow((row, rowIndex) => {
                sheetData.rows[(rowIndex - 1).toString()] = { cells: {} };

                if (sheet.getRow(rowIndex).height) {
                  xs.data.rows.setHeight(
                    rowIndex,
                    sheet.getRow(rowIndex).height
                  );
                } else {
                  sheet.getRow(rowIndex).height = 25;
                }
                // console.log(
                //   "row高设置了也无效 ",
                //   xs.data.rows.getOrNew(rowIndex),
                //   xs.data.rows.getHeight(rowIndex),
                //   sheet.getRow(rowIndex).height
                // );

                //includeEmpty = false 不包含空白单元格
                row.eachCell(
                  { includeEmpty: true },
                  function (cell, colNumber) {
                    // console.log('原始cell', cell);

                    let cellType = cell.type;
                    let cellText = "";
                    let cellformula = (cell.value && cell.value.formula) || "";
                    let cellsharedFormula =
                      (cell.value && cell.value.sharedFormula) || "";
                    if (cell.value && cell.value.result) {
                      // Excel 单元格有公式
                      if (cell.value.result && cell.value.result.error) {
                        // Excel 单元格有公式错误
                        cellText = cell.value.result.error;
                      } else {
                        cellText = cell.value.result || "";
                      }
                    } else if (cell.value && cell.value.formula) {
                      cellText = "=" + cell.value.formula;
                    } else if (
                      (cell.value && cell.value.formula) ||
                      (cell.value && cell.value.sharedFormula)
                    ) {
                      cellText = "0";
                    } else if (cell.value && cell.value.richText) {
                      // Excel 单元格是多行文本
                      for (let text in cell.value.richText) {
                        // 多行文本做累加
                        cellText += cell.value.richText[text].text;
                      }
                    } else {
                      // Excel 单元格无公式
                      // cellText = JSON.stringify(cell.value);
                      cellText = cell.value || "";
                    }

                    //解析单元格,包含样式
                    //*********************单元格存在背景色******************************
                    // 单元格存在背景色
                    let backGroundColor = null;

                    if (
                      cell.style.fill &&
                      cell.style.fill.fgColor &&
                      cell.style.fill.fgColor.argb
                    ) {
                      // 8位字符颜色先转rgb再转16进制颜色
                      backGroundColor = ((val) => {
                        val = val.trim().toLowerCase(); //去掉前后空格
                        let color = {};
                        try {
                          let argb =
                            /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(
                              val
                            );
                          color.r = parseInt(argb[2], 16);
                          color.g = parseInt(argb[3], 16);
                          color.b = parseInt(argb[4], 16);
                          color.a = parseInt(argb[1], 16) / 255;
                          return tinycolor(
                            `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a})`
                          ).toHexString();
                        } catch (e) {
                          console.log(e);
                        }
                      })(cell.style.fill.fgColor.argb);
                    }

                    if (backGroundColor) {
                      cell.style.bgcolor = backGroundColor;
                    }
                    //*************************************************************************** */

                    //*********************字体存在背景色******************************
                    // 字体颜色
                    let fontColor = null;
                    if (
                      cell.style.font &&
                      cell.style.font.color &&
                      cell.style.font.color.argb
                    ) {
                      // 8位字符颜色先转rgb再转16进制颜色
                      fontColor = ((val) => {
                        val = val.trim().toLowerCase(); //去掉前后空格
                        let color = {};
                        try {
                          let argb =
                            /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(
                              val
                            );
                          color.r = parseInt(argb[2], 16);
                          color.g = parseInt(argb[3], 16);
                          color.b = parseInt(argb[4], 16);
                          color.a = parseInt(argb[1], 16) / 255;
                          return tinycolor(
                            `rgba(${color.r}, ${color.g}, ${color.b}, ${color.a})`
                          ).toHexString();
                        } catch (e) {
                          console.log(e);
                        }
                      })(cell.style.font.color.argb);
                    }
                    if (fontColor) {
                      //console.log(fontColor)
                      cell.style.color = fontColor;
                    }
                    //************************************************************************ */

                    // exceljs 对齐的格式转成 x-date-spreedsheet 能识别的对齐格式
                    if (
                      cell.style.alignment &&
                      cell.style.alignment.horizontal
                    ) {
                      cell.style.align = cell.style.alignment.horizontal;
                      cell.style.valign = cell.style.alignment.vertical;
                    }

                    //处理合并单元格
                    let mergeAddress = _.find(mergeAddressData, function (o) {
                      return o.startAddress == cell._address;
                    });
                    if (mergeAddress) {
                      // 遍历的单元格属于合并单元格
                      if (cell.master.address != mergeAddress.startAddress) {
                        // 不是合并单元格中的第一个单元格不需要计入数据源
                        return;
                      }
                      // 说明是合并单元格区域的起始单元格
                      sheetData.rows[(rowIndex - 1).toString()].cells[
                        (colNumber - 1).toString()
                      ] = {
                        address: cell._address,
                        text: cellText,
                        formula: cellformula,
                        sharedFormula: cellsharedFormula,
                        type: cellType,
                        style: 0,
                        merge: [mergeAddress.YRange, mergeAddress.XRange],
                      };

                      //解析单元格,包含样式
                      let xsCellStyle = _.cloneDeep(cell.style);
                      xsCellStyle.border = {};
                      // 边框线
                      if (
                        cell.style.border &&
                        JSON.stringify(cell.style.border) != "{}"
                      ) {
                        let coloneStyle = cell.style.border;
                        xsCellStyle.border = {};
                        if (coloneStyle.bottom) {
                          xsCellStyle.border.bottom = [];
                          xsCellStyle.border.bottom[0] =
                            coloneStyle.bottom.style;
                          if (_.isString(coloneStyle.bottom.color)) {
                            xsCellStyle.border.bottom[1] =
                              coloneStyle.bottom.color;
                          } else {
                            xsCellStyle.border.bottom[1] = "#000000";
                          }
                        }
                        if (coloneStyle.right) {
                          xsCellStyle.border.right = [];
                          xsCellStyle.border.right[0] = coloneStyle.right.style;
                          if (_.isString(coloneStyle.right.color)) {
                            xsCellStyle.border.right[1] =
                              coloneStyle.right.color;
                          } else {
                            xsCellStyle.border.right[1] = "#000000";
                          }
                        }
                        if (coloneStyle.left) {
                          xsCellStyle.border.left = [];
                          xsCellStyle.border.left[0] = coloneStyle.left.style;
                          if (_.isString(coloneStyle.left.color)) {
                            xsCellStyle.border.left[1] = coloneStyle.left.color;
                          } else {
                            xsCellStyle.border.left[1] = "#000000";
                          }
                        }
                        if (coloneStyle.top) {
                          xsCellStyle.border.top = [];
                          xsCellStyle.border.top[0] = coloneStyle.top.style;
                          if (_.isString(coloneStyle.top.color)) {
                            xsCellStyle.border.top[1] = coloneStyle.top.color;
                          } else {
                            xsCellStyle.border.top[1] = "#000000";
                          }
                        }
                      }

                      sheetData.styles.push(xsCellStyle);
                      //对应的style存放序号
                      sheetData.rows[(rowIndex - 1).toString()].cells[
                        (colNumber - 1).toString()
                      ].style = sheetData.styles.length - 1;
                    } else {
                      // 非合并单元格
                      sheetData.rows[(rowIndex - 1).toString()].cells[
                        (colNumber - 1).toString()
                      ] = {
                        address: cell._address,
                        text: cellText,
                        style: 0,
                        formula: cellformula,
                        sharedFormula: cellsharedFormula,
                        type: cellType,
                      };
                      //解析单元格,包含样式
                      let xsCellStyle = _.cloneDeep(cell.style);
                      xsCellStyle.border = {};

                      // 边框线
                      if (
                        cell.style.border &&
                        JSON.stringify(cell.style.border) != "{}"
                      ) {
                        let coloneStyle = cell.style.border;
                        xsCellStyle.border = {};
                        if (coloneStyle.bottom) {
                          xsCellStyle.border.bottom = [];
                          xsCellStyle.border.bottom[0] =
                            coloneStyle.bottom.style;
                          if (_.isString(coloneStyle.bottom.color)) {
                            xsCellStyle.border.bottom[1] =
                              coloneStyle.bottom.color;
                          } else {
                            xsCellStyle.border.bottom[1] = "#000000";
                          }
                        }
                        if (coloneStyle.right) {
                          xsCellStyle.border.right = [];
                          xsCellStyle.border.right[0] = coloneStyle.right.style;
                          if (_.isString(coloneStyle.right.color)) {
                            xsCellStyle.border.right[1] =
                              coloneStyle.right.color;
                          } else {
                            xsCellStyle.border.right[1] = "#000000";
                          }
                        }
                        if (coloneStyle.left) {
                          xsCellStyle.border.left = [];
                          xsCellStyle.border.left[0] = coloneStyle.left.style;
                          if (_.isString(coloneStyle.left.color)) {
                            xsCellStyle.border.left[1] = coloneStyle.left.color;
                          } else {
                            xsCellStyle.border.left[1] = "#000000";
                          }
                        }
                        if (coloneStyle.top) {
                          xsCellStyle.border.top = [];
                          xsCellStyle.border.top[0] = coloneStyle.top.style;
                          if (_.isString(coloneStyle.top.color)) {
                            xsCellStyle.border.top[1] = coloneStyle.top.color;
                          } else {
                            xsCellStyle.border.top[1] = "#000000";
                          }
                        }
                      }

                      sheetData.styles.push(xsCellStyle);
                      // console.log("sheetData.styles1", sheetData.styles);

                      //对应的style存放序号
                      sheetData.rows[(rowIndex - 1).toString()].cells[
                        (colNumber - 1).toString()
                      ].style = sheetData.styles.length - 1;
                      // console.log(
                      //   "sheetData.styles2",
                      //   sheetData.styles[
                      //     sheetData.rows[(rowIndex - 1).toString()].cells[
                      //       (colNumber - 1).toString()
                      //     ].style
                      //   ]
                      //   // sheetData.rows[(rowIndex - 1).toString()].cells[
                      //   //   (colNumber - 1).toString()
                      //   // ].style
                      // );
                    }
                  }
                );
              });
              workbookData.push(sheetData);
            });
            // 找出 cols 和 rows 字段长度的最大值作为表格的行列数
            const { maxColsProps, maxRowsProps } = workbookData.reduce(
              (acc, current) => {
                return {
                  maxColsProps: Math.max(
                    acc.maxColsProps,
                    Object.keys(current.cols).length
                  ),
                  maxRowsProps: Math.max(
                    acc.maxRowsProps,
                    Object.keys(current.rows).length
                  ),
                };
              },
              { maxColsProps: 0, maxRowsProps: 0 }
            );
            // this.maxColsProps = maxColsProps;
            // this.maxRowsProps = maxRowsProps;
            this.$emit("maxTableLength", {
              maxColsProps,
              maxRowsProps,
            });
            this.maxColsProps = maxColsProps;
            this.maxRowsProps = maxRowsProps;
            console.log("workbookData", workbookData);
            this.loadData(workbookData);
          });
        };
      }
    },
    // 导出excel
    exportExcel(fileName, sheets) {
      const exceljsWorkbook = new Excel.Workbook();
      exceljsWorkbook.modified = new Date();

      let sheetsdata = sheets ? sheets : this.xs.getData();
      console.log("sheetsdata", sheetsdata, xs.getData());
      sheetsdata.forEach(function (xws) {
        console.log("xws", xws);
        let rowobj = xws.rows || xws[0].rows;
        // 构造exceljs文档结构
        const exceljsSheet = exceljsWorkbook.addWorksheet(xws.name);
        // 读取列宽
        let sheetColumns = [];
        let colIndex = 0;
        for (let col in xws.cols) {
          console.log("xws.cols[col]", xws.cols[col]);

          if (xws.cols[col].width) {
            sheetColumns.push({
              header: colIndex + "",
              key: colIndex + "",
              width: xws.cols[col].width,
              height: 1000,
            });
          }
          colIndex++;
        }
        exceljsSheet.columns = sheetColumns;
        for (let ri = 0; ri < rowobj.len; ++ri) {
          let row = rowobj[ri];
          if (!row) continue;
          // 构造exceljs的行(如果尚不存在，则将返回一个新的空对象)
          const exceljsRow = exceljsSheet.getRow(ri + 1);
          Object.keys(row.cells).forEach(function (k) {
            let idx = +k;
            if (isNaN(idx)) return;
            const exceljsCell = exceljsRow.getCell(Number(k) + 1);
            // console.log("exceljsCell", exceljsCell);
            if (row.cells[k].formula) {
              exceljsCell.value = {
                result: row.cells[k].text,
                formula: row.cells[k].formula,
              };
            } else if (row.cells[k].sharedFormula) {
              exceljsCell.value = {
                sharedFormula: row.cells[k].sharedFormula,
              };
            } else {
              exceljsCell.value = row.cells[k].text;
            }
            // exceljsCell.value.type = row.cells[k].type || "";
            // exceljsCell.value = {
            //     result: row.cells[k].text || '',
            //     formula: row.cells[k].formula || '',
            //     sharedFormula: row.cells[k].sharedFormula || '',
            //     type: row.cells[k].type || ''

            //   };
            if (
              xws.styles &&
              xws.styles.length > 0 &&
              xws.styles[row.cells[k].style]
            ) {
              // 垂直对齐方式
              if (xws.styles[row.cells[k].style].valign) {
                if (
                  exceljsCell.alignment == undefined ||
                  exceljsCell.alignment == null
                ) {
                  exceljsCell.alignment = {};
                }
                exceljsCell.alignment.vertical =
                  xws.styles[row.cells[k].style].valign;
              }
              // 水平对齐方式
              if (xws.styles[row.cells[k].style].align) {
                if (
                  exceljsCell.alignment == undefined ||
                  exceljsCell.alignment == null
                ) {
                  exceljsCell.alignment = {};
                }
                exceljsCell.alignment.horizontal =
                  xws.styles[row.cells[k].style].align;
              }
              // exceljsSheet.getCell(exceljsCell._address).alignment = { vertical: xws.styles[row.cells[k].style].valign, horizontal: xws.styles[row.cells[k].style].align }
            }

            // 边框
            if (
              xws.styles &&
              xws.styles.length > 0 &&
              xws.styles[row.cells[k].style] &&
              JSON.stringify(xws.styles[row.cells[k].style]) != "{}" &&
              JSON.stringify(xws.styles[row.cells[k].style].border) != "{}"
            ) {
              //exceljsCell.border = xws.styles[row.cells[k].style].border;
              exceljsCell.border = {};
              // bottom
              if (
                xws.styles[row.cells[k].style].border.bottom &&
                Array.isArray(xws.styles[row.cells[k].style].border.bottom) &&
                xws.styles[row.cells[k].style].border.bottom.length == 2
              ) {
                exceljsCell.border.bottom = {};
                exceljsCell.border.bottom.style =
                  xws.styles[row.cells[k].style].border.bottom[0];
                exceljsCell.border.bottom.color = {};
                //exceljsCell.border.bottom.color.indexed = 64
                exceljsCell.border.bottom.color =
                  xws.styles[row.cells[k].style].border.bottom[1];
              }
              // left
              if (
                xws.styles[row.cells[k].style].border.left &&
                Array.isArray(xws.styles[row.cells[k].style].border.left) &&
                xws.styles[row.cells[k].style].border.left.length == 2
              ) {
                exceljsCell.border.left = {};
                exceljsCell.border.left.style =
                  xws.styles[row.cells[k].style].border.left[0];
                exceljsCell.border.left.color = {};
                //exceljsCell.border.left.color.indexed = 64
                exceljsCell.border.left.color =
                  xws.styles[row.cells[k].style].border.left[1];
              }
              // right
              if (
                xws.styles[row.cells[k].style].border.right &&
                Array.isArray(xws.styles[row.cells[k].style].border.right) &&
                xws.styles[row.cells[k].style].border.right.length == 2
              ) {
                exceljsCell.border.right = {};
                exceljsCell.border.right.style =
                  xws.styles[row.cells[k].style].border.right[0];
                exceljsCell.border.right.color = {};
                //exceljsCell.border.right.color.indexed = 64
                exceljsCell.border.right.color =
                  xws.styles[row.cells[k].style].border.right[1];
              }
              // top
              if (
                xws.styles[row.cells[k].style].border.top &&
                Array.isArray(xws.styles[row.cells[k].style].border.top) &&
                xws.styles[row.cells[k].style].border.top.length == 2
              ) {
                exceljsCell.border.top = {};
                exceljsCell.border.top.style =
                  xws.styles[row.cells[k].style].border.top[0];
                exceljsCell.border.top.color = {};
                //exceljsCell.border.right.color.indexed = 64
                exceljsCell.border.top.color =
                  xws.styles[row.cells[k].style].border.top[1];
              }
            }

            // 背景色

            if (
              xws.styles &&
              xws.styles.length > 0 &&
              xws.styles[row.cells[k].style] &&
              xws.styles[row.cells[k].style].bgcolor
            ) {
              let rgb = tinycolor(
                xws.styles[row.cells[k].style].bgcolor
              ).toRgb();
              let rHex = parseInt(rgb.r).toString(16).padStart(2, "0");
              let gHex = parseInt(rgb.g).toString(16).padStart(2, "0");
              let bHex = parseInt(rgb.b).toString(16).padStart(2, "0");
              let aHex = parseInt(rgb.a).toString(16).padStart(2, "0");
              let _bgColor = aHex + rHex + gHex + bHex;
              // 设置exceljs背景色
              exceljsCell.fill = {
                type: "pattern",
                pattern: "solid",
                fgColor: { argb: _bgColor },
              };
            }
            // 字体
            if (
              xws.styles &&
              xws.styles.length > 0 &&
              xws.styles[row.cells[k].style] &&
              xws.styles[row.cells[k].style].font
            ) {
              exceljsCell.font = xws.styles[row.cells[k].style].font;
            }

            // 字体颜色
            if (
              xws.styles &&
              xws.styles.length > 0 &&
              xws.styles[row.cells[k].style] &&
              xws.styles[row.cells[k].style].color
            ) {
              let rgb = tinycolor(xws.styles[row.cells[k].style].color).toRgb();
              let rHex = parseInt(rgb.r).toString(16).padStart(2, "0");
              let gHex = parseInt(rgb.g).toString(16).padStart(2, "0");
              let bHex = parseInt(rgb.b).toString(16).padStart(2, "0");
              let aHex = parseInt(rgb.a).toString(16).padStart(2, "0");
              let _fontColor = aHex + rHex + gHex + bHex;
              exceljsCell.font.color = { argb: _fontColor };
            }
            // 合并单元格
            if (row.cells[k].merge) {
              // 开始行
              let startRow = ri + 1;
              // 结束行,加上Y轴跨度
              let endRow = startRow + row.cells[k].merge[0];
              // 开始列
              let startColumn = Number(k) + 1;
              // 结束列,加上X轴跨度
              let endColumn = startColumn + row.cells[k].merge[1];
              // 按开始行，开始列，结束行，结束列合并
              exceljsSheet.mergeCells(startRow, startColumn, endRow, endColumn);
            }
          });
        }
      });
      // return;
      // writeBuffer 把写好的excel 转换成 ArrayBuffer 类型
      exceljsWorkbook.xlsx.writeBuffer().then(async (data) => {
        const link = document.createElement("a");
        // Blob 实现下载excel
        const blob = new Blob([data], {
          type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=UTF-8",
        });
        // 创建 FormData 对象
        const formData = new FormData();
        formData.append("file", blob, `${fileName}.xlsx`);
        let response = await postUploadFilePrivate(formData);
        if (response.data && response.data.bcode == 0) {
          this.$emit("getFileId", response.data.bdata);
        } else {
          this.$emit("getFileId", "");
        }
        link.href = window.URL.createObjectURL(blob);
        link.download = `${fileName}.xlsx`;
        link.click();
      });
    },
    // 导出json
    exportJson() {
      let sheetsData = this.xs.getData();
      let jsonData = [];
      sheetsData.forEach((sheet) => {
        let rows = Object.entries(sheet.rows);
        if (
          Array.isArray(this.ExportJsonProperties) &&
          this.ExportJsonProperties.length > 0
        ) {
          // 遍历数据，跳过第一行表头
          for (let i = 1; i < rows.length; i++) {
            if (rows[i] && rows[i][1] && rows[i][1].cells) {
              let row = Object.entries(rows[i][1].cells);
              // 构造行对象
              let JsonRow = {};
              for (let k = 0; k < row.length; k++) {
                let cells = row[k];
                JsonRow[this.ExportJsonProperties[k]] = cells[1].text;
              }
              jsonData.push(JsonRow);
            }
          }
        }
      });

      return jsonData;
    },
    //让底部sheet数量超出宽度时能用滚轮滚动来选择sheet
    scrollInit() {
      // 获取要绑定事件的元素
      const nav = document.querySelector(".x-spreadsheet-menu");
      // document.addEventListener('DOMMouseScroll', handler, false)
      // 添加滚轮滚动监听事件，一般是用下面的方法，上面的是火狐的写法
      nav.addEventListener("mousewheel", handler, false);
      // 滚动事件的出来函数
      function handler(event) {
        // 获取滚动方向
        const detail = event.wheelDelta || event.detail;
        // 定义滚动方向，其实也可以在赋值的时候写
        const moveForwardStep = 1;
        const moveBackStep = -1;
        // 定义滚动距离
        let step = 0;
        // 判断滚动方向,这里的100可以改，代表滚动幅度，也就是说滚动幅度是自定义的
        if (detail < 0) {
          step = moveForwardStep * 100;
        } else {
          step = moveBackStep * 100;
        }
        // 对需要滚动的元素进行滚动操作
        nav.scrollLeft += step;
      }
    },
  },
  destroyed() {},
};
</script>
<style>
.x-spreadsheet-scrollbar.horizontal {
  width: 99% !important;
}
.x-spreadsheet-menu {
  display: flex;
  overflow-x: auto;
}
.x-spreadsheet-menu::-webkit-scrollbar {
  width: 0; /* 滚动条宽度 */
  height: 0;
}
.x-spreadsheet-menu li:nth-child(1) {
  position: absolute;
  z-index: 999;
  background-color: #f5f6f7;
}
.x-spreadsheet-menu li:nth-child(2) {
  margin-left: 90px;
}
</style>
